package com.karrim.server;

import com.google.common.base.Optional;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.karrim.server.abstr.AbstractDispatcher;
import com.karrim.server.annotation.Annotation.HttpPort;
import com.karrim.server.factory.GreeterFactory;
import com.karrim.server.factory.SocketConnectionEventFactory;
import com.karrim.server.util.array.DynamicList;
import com.karrim.server.util.array.def.Array;
import com.karrim.server.util.def.Listener;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * Resources: > http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol >
 * http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
 *
 * @author andrea.cantafio
 */
@Singleton
public class Server extends Thread {

    /**
     * Creates a new {@link com.karrim.server.Server} instance listening on specified port
     *
     * @param port port that will be used to listen for incoming connections
     * @throws IOException if an error occurs while
     */
    @Inject
    public Server(@HttpPort int port) throws IOException {
        this(port, Optional.fromNullable((Integer) null));
    }

    public Server(int port, Optional<Integer> backlog) throws IOException {
        this(new int[]{port}, backlog);
    }

    public Server(int... ports) throws IOException {
        this(ports, Optional.fromNullable((Integer) null));
    }

    public Server(int[] ports, Optional<Integer> backlog) throws IOException {
        super("Server");
        for (int port : ports) {
            if (backlog.isPresent()) {
                sockets.add(new ServerSocket(port, backlog.get()));
            } else {
                sockets.add(new ServerSocket(port));
            }
        }
    }

    @Override
    public void run() {
        /* Creating and storing greeter threads */
        Iterator<ServerSocket> iterator = sockets.iterator();
        while (iterator.hasNext()) {
            greeters.add(greeterFactory.create(iterator.next()));
        }
        while (true) {

        }
    }

    @Inject
    public void setGreeterFactory(GreeterFactory factory) {
        greeterFactory = factory;
    }

    @Inject
    public void setSocketConnectionEventDispatcher(SocketConnectionEventDispatcher dispatcher) {
        this.dispatcher = dispatcher;
    }

    @Inject
    public void setSocketConnectionEventFactory(SocketConnectionEventFactory factory) {
        eventFactory = factory;
    }

    @Override
    public void interrupt() {
        interrupted = true;
        super.interrupt();
    }
    private SocketConnectionEventDispatcher dispatcher = new SocketConnectionEventDispatcher();
    private SocketConnectionEventFactory eventFactory;
    private GreeterFactory greeterFactory;
    private Array<Thread> greeters = new DynamicList<>();
    private boolean interrupted = false;
    private Array<ServerSocket> sockets = new DynamicList<>();
    /*
     Common Port Assignments and Corresponding RFC Numbers

     Port Common Name RFC#  Purpose
     7     Echo        862   Echoes data back. Used mostly for testing.
     9     Discard     863   Discards all data sent to it. Used mostly for testing.
     13    Daytime     867   Gets the date and time.
     17    Quotd       865   Gets the quote of the day.
     19    Chargen     864   Generates characters. Used mostly for testing.
     20    ftp-data    959   Transfers files. FTP stands for File Transfer Protocol.
     21    ftp         959   Transfers files as well as commands.
     23    telnet      854   Logs on to remote systems.
     25    SMTP        821   Transfers Internet mail. Stands for Simple Mail Transfer Protocol.
     37    Time        868   Determines the system time on computers.
     43    whois       954   Determines a user's name on a remote system.
     70    gopher     1436   Looks up documents, but has been mostly replaced by HTTP.
     79    finger     1288   Determines information about users on other systems.
     80    http       1945   Transfer documents. Forms the foundation of the Web.
     110   pop3       1939   Accesses message stored on servers. Stands for Post Office Protocol, version 3.
     443   https      n/a    Allows HTTP communications to be secure. Stands for Hypertext Transfer Protocol over Secure Sockets Layer (SSL).
     */
    public static final int PORT_ECHO = 7,
            PORT_DISCARD = 9,
            PORT_DAYTIME = 13,
            PORT_QUOTD = 17,
            PORT_CHAR_GEN = 19,
            PORT_FTP_DATA = 20,
            PORT_FTP = 21,
            PORT_TELNET = 23,
            PORT_SMTP = 25,
            PORT_TIME = 37,
            PORT_WHOIS = 43,
            PORT_GOPHER = 70,
            PORT_FINGER = 79,
            PORT_HTTP = 80,
            PORT_POP3 = 110,
            PORT_HTTPS = 443;
}
